package middleware

import (
	"bolt-manager/model"
	"encoding/json"
	"fmt"
	log "github.com/sirupsen/logrus"
	"net/http"
	"reflect"
	"runtime"
	"strings"
)

// 全局异常恢复
func GlobalRecover(next http.HandlerFunc) http.HandlerFunc {
	return func (w http.ResponseWriter, r *http.Request) {
		defer func() {
			if err := recover(); err != nil {
				// 详细堆栈信息
				var callers []string
				for i := 1; ; i++ {
					_, file, line, got := runtime.Caller(i)
					if !got {
						break
					}
					callers = append(callers, fmt.Sprintf("%s:%d", file, line))
				}

				// 日志记录使用的详细错误信息
				var errMessage string
				// 返回信息
				var errResponse model.ErrorResponse

				// 判断异常类型是否为主动抛出
				if reflect.TypeOf(err) == reflect.TypeOf(model.ErrorResponse{}) {
					errResponse = err.(model.ErrorResponse)
					errMessage = errResponse.Message
				} else {
					errResponse = model.NewError()
					errMessage = fmt.Sprintf("%s", err)
				}

				// 拼接异常信息内容
				logMessage := fmt.Sprintf("[全局异常] 状态码：%d，异常信息：%s\n", errResponse.Code, errMessage)
				logMessage += fmt.Sprintf("%s", strings.Join(callers, "\n"))
				log.Error(logMessage)

				// 返回错误信息
				jsonByte, _ := json.Marshal(errResponse)
				w.Header().Set("Content-Type", "application/json")
				w.Write(jsonByte)
			}
		}()

		next(w, r)
	}
}
